package cn.ycc1.mymiddle.rag;

import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.QuestionAnswerAdvisor;
import org.springframework.ai.vectorstore.VectorStore;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author ycc
 * @date 2025/5/2
 * Spring AI 高级RAG功能实现
 * 3.1 Multi Query Expansion (多查询扩展)
 * 多查询扩展是提高RAG系统检索效果的关键技术。在实际应用中，用户的查询往往是简短且不完整的，这可能导致检索结果不够准确或完整。
 * Spring AI提供了强大的多查询扩展机制，能够自动生成多个相关的查询变体，从而提高检索的准确性和召回率。
 * 3.2 Query Rewrite (查询重写)
 * 查询重写是RAG系统中的一个重要优化技术，它能够将用户的原始查询转换成更加结构化和明确的形式。
 * 这种转换可以提高检索的准确性，并帮助系统更好地理解用户的真实意图。
 * 3.3 Query Translation (查询翻译)
 * 查询翻译是RAG系统中的一个实用功能，它能够将用户的查询从一种语言翻译成另一种语言。这对于多语言支持和跨语言检索特别有用。
 * Spring AI提供了TranslationQueryTransformer来实现这一功能。
 * 3.4 Context-aware Queries (上下文感知查询)
 * 在实际对话中，用户的问题往往依赖于之前的对话上下文。
 * 3.5 文档合并器（DocumentJoiner）
 * 在实际应用中，我们经常需要从多个查询或多个数据源获取文档。为了有效地管理和整合这些文档，Spring AI提供了ConcatenationDocumentJoiner文档合并器。这个工具可以将多个来源的文档智能地合并成一个统一的文档集合。
 *
 * 文档合并器的主要特点：
 *
 * 智能去重：当存在重复文档时，只保留第一次出现的文档
 * 分数保持：合并过程中保持每个文档的原始相关性分数
 * 多源支持：支持同时处理来自不同查询和不同数据源的文档
 * 顺序维护：保持文档的原始检索顺序
 * 3.6 检索增强顾问（RetrievalAugmentationAdvisor）
 * RetrievalAugmentationAdvisor是Spring AI提供的一个强大工具，它能够自动化地处理文档检索和查询增强过程。
 * 这个顾问组件将文档检索与查询处理无缝集成，使得AI助手能够基于检索到的相关文档提供更准确的回答。
 * 3.7 Document Selection (文档选择)
 * 在理解了检索增强顾问的基础上，我们来看看更复杂的文档选择机制。文档选择是RAG系统的核心组件之一，它决定了系统能够为用户提供多么准确和相关的信息。
 * 每个文档包含两个主要部分：
 * 文档内容：结构化的文本描述，包含项目编号、概述、详细信息等
 * 元数据：用于快速筛选和分类的键值对，如类型、年份、位置等
 * 3.8 Error Handling and Edge Cases (错误处理和边界情况)
 * 在生产环境中，RAG系统需要优雅地处理各种边界情况，特别是文档检索失败或相关文档未找到的情况。
 *
 * 最佳实践：
 * 在实际部署和运营RAG系统时，我们需要从多个维度来考虑系统的最佳实践。
 * 4.1文档处理最佳实践
 * 4.2检索增强策略
 * 4.3系统配置最佳实践
 * 4.4错误处理机制
 * 4.5 系统角色设定
 * 4.6 性能优化建议
 */
@RestController
@RequestMapping("/rag")
public class RagController {

    @Autowired
    private ChatClient chatClient;

    @Autowired
    private VectorStore vectorStore;


    // @PostMapping(value = "/chat", produces = "text/plain; charset=UTF-8")
    @GetMapping(value = "/chat", produces = "text/plain; charset=UTF-8")
    public String generation(String message) {
        // 发起聊天请求并处理响应
        return chatClient.prompt()
                .user(message)
                .advisors(new QuestionAnswerAdvisor(vectorStore))
                .call()
                .content();
    }
}
